package com.yundingai.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yundingai.domain.entity.AllMenu;
import com.yundingai.domain.entity.RelRoleMenu;
import com.yundingai.domain.entity.vo.AllMenuVo;
import com.yundingai.domain.vo.MenuVo;
import com.yundingai.context.UserContext;
import com.yundingai.mapper.AllUserMapper;
import com.yundingai.mapper.RelRoleMenuMapper;
import com.yundingai.service.AllMenuService;
import com.yundingai.mapper.AllMenuMapper;
import lombok.extern.slf4j.Slf4j;
import org.junit.platform.commons.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* @author liyuxiang
* @description 针对表【all_menu(菜单表：用于动态查询生成后台菜单与动态路由实现)】的数据库操作Service实现
* @createDate 2025-07-16 12:43:19
*/
@Slf4j
@Service
@Transactional
public class AllMenuServiceImpl extends ServiceImpl<AllMenuMapper, AllMenu> implements AllMenuService {

    @Autowired
    private AllMenuMapper allMenuMapper;
    @Autowired
    private AllUserMapper allUserMapper;
    @Autowired
    private RelRoleMenuMapper relRoleMenuMapper;

    // 常量定义
    private static final Integer ADMIN_ROLE_ID = 1; // 根据实际业务调整
    private static final String MENU_CREATOR_PREFIX = "user_";

    @Override
    public List<AllMenu> selectAllMenusByUsername(String username) {
        if (StringUtils.isBlank(username)) {
            log.warn("查询菜单时用户名参数为空");
            return Collections.emptyList();
        }
        return allMenuMapper.selectAllMenusByUsername(username);
    }

    @Override
    public void updateMenu(AllMenu allMenu) {
        if (allMenu == null || allMenu.getMenuId() == null) {
            throw new IllegalArgumentException("菜单信息或菜单ID不能为空");
        }
        allMenuMapper.updateById(allMenu);
    }

    @Override
    public void insertMenu(AllMenuVo allMenuVo) {
        validateMenu(allMenuVo);
        setCreatorInfo(allMenuVo);

        allMenuMapper.insert(allMenuVo);

        assignMenuToCurrentUserRole(allMenuVo.getMenuId(), UserContext.getUserId());
    }

    @Override
    public List<MenuVo> selectAllMenusByUserRoleId(String roleId) {
        if (StringUtils.isBlank(roleId)) {
            log.warn("角色ID参数为空");
            return Collections.emptyList();
        }

        List<RelRoleMenu> relRoleMenus = relRoleMenuMapper.selectList(
                new LambdaQueryWrapper<RelRoleMenu>().eq(RelRoleMenu::getRoleId, roleId));
        log.info("角色ID: {} 关联的菜单关系数量: {}", roleId, relRoleMenus.size());

        if (CollectionUtils.isEmpty(relRoleMenus)) {
            log.warn("角色ID: {} 没有关联任何菜单", roleId);
            return Collections.emptyList();
        }

        List<Integer> menuIds = relRoleMenus.stream()
                                            .map(RelRoleMenu::getMenuId)
                                            .distinct()
                                            .collect(Collectors.toList());
        log.info("角色ID: {} 关联的菜单ID列表: {}", roleId, menuIds);

        List<AllMenu> allMenus = queryAvailableMenus()
                .in(AllMenu::getMenuId, menuIds)
                .list();
        log.info("角色ID: {} 查询到的可用菜单数量: {}", roleId, allMenus.size());
        
        // 查找需要的父菜单，排除已有的菜单ID
        Set<Integer> existingMenuIds = allMenus.stream()
                .map(AllMenu::getMenuId)
                .collect(Collectors.toSet());
        
        Set<Integer> parentIds = allMenus.stream()
                .map(AllMenu::getParentId)
                .filter(parentId -> parentId != null && parentId != 0)
                .filter(parentId -> !existingMenuIds.contains(parentId)) // 排除已有的菜单
                .collect(Collectors.toSet());
        
        if (!parentIds.isEmpty()) {
            List<AllMenu> parentMenus = queryAvailableMenus()
                    .in(AllMenu::getMenuId, parentIds)
                    .list();
            log.info("角色ID: {} 额外查询到的父菜单数量: {}", roleId, parentMenus.size());
            log.info("父菜单ID列表: {}", parentMenus.stream().map(AllMenu::getMenuId).collect(Collectors.toList()));
            allMenus.addAll(parentMenus);
        }

        List<MenuVo> result = buildMenuTree(allMenus);
        log.info("角色ID: {} 构建树形结构后的菜单数量: {}", roleId, result.size());
        return result;
    }

    @Override
    public List<MenuVo> selectAllMenus() {
        Integer userId = UserContext.getUserId();
        if (userId == null) {
            log.warn("未获取到当前用户ID");
            return Collections.emptyList();
        }

        if (isAdmin(userId)) {
            log.debug("管理员用户，返回所有可用菜单");
            return buildFullMenuTree();
        }
        return selectMenusByUserId(userId);
    }

    @Override
    public List<MenuVo> selectMenusByCurrentUser() {
        return selectMenusByUserId(UserContext.getUserId());
    }

    @Override
    public MenuVo selectMenuById(Integer menuId) {
        if (menuId == null) {
            throw new IllegalArgumentException("菜单ID不能为空");
        }

        AllMenu menu = allMenuMapper.selectById(menuId);
        if (menu == null) {
            return null;
        }

        MenuVo menuVo = new MenuVo(menu);
        menuVo.setChildren(queryChildMenus(menuId));
        return menuVo;
    }

    @Override
    public void deleteMenu(Integer menuId) {
        if (menuId == null) {
            throw new IllegalArgumentException("菜单ID不能为空");
        }

        if (hasChildren(menuId)) {
            throw new IllegalStateException("请先删除子菜单");
        }

        allMenuMapper.deleteById(menuId);
        relRoleMenuMapper.delete(
                new LambdaQueryWrapper<RelRoleMenu>().eq(RelRoleMenu::getMenuId, menuId));
    }

    @Override
    public void insertChildMenu(AllMenuVo allMenuVo) {
        if (allMenuVo.getParentId() == null) {
            throw new IllegalArgumentException("子菜单必须指定父菜单ID");
        }

        validateMenu(allMenuVo);
        setCreatorInfo(allMenuVo);

        allMenuMapper.insert(allMenuVo);

        assignMenuToCurrentUserRole(allMenuVo.getMenuId(), UserContext.getUserId());
    }

    @Override
    public List<MenuVo> selectMenusByUserId(Integer userId) {
        if (userId == null) {
            log.warn("用户ID参数为空");
            return Collections.emptyList();
        }

        Integer roleId = allUserMapper.findUserRoleByUserId(userId);
        if (roleId == null) {
            log.warn("用户ID: {} 没有关联的角色", userId);
            return Collections.emptyList();
        }
        
        log.info("用户ID: {} 对应的角色ID: {}", userId, roleId);
        List<MenuVo> result = selectAllMenusByUserRoleId(String.valueOf(roleId));
        log.info("用户ID: {} 最终查询到的菜单数量: {}", userId, result.size());
        return result;
    }

    // ============ 私有辅助方法 ============

    private LambdaQueryChainWrapper<AllMenu> queryAvailableMenus() {
        return new LambdaQueryChainWrapper<>(allMenuMapper)
                .eq(AllMenu::getIsAvaliable, 1)
                .orderByAsc(AllMenu::getMenuId);
    }

    private List<MenuVo> buildMenuTree(List<AllMenu> menus) {
        if (CollectionUtils.isEmpty(menus)) {
            log.info("输入的菜单列表为空");
            return Collections.emptyList();
        }
        
        log.info("开始构建菜单树，输入菜单数量: {}", menus.size());
        menus.forEach(menu -> log.debug("菜单: ID={}, ParentID={}, Title={}", 
            menu.getMenuId(), menu.getParentId(), menu.getMenuTitle()));

        Map<Integer, MenuVo> menuMap = menus.stream()
                                            .map(MenuVo::new)
                                            .collect(Collectors.toMap(MenuVo::getMenuId, Function.identity()));
        log.info("转换为MenuVo后的数量: {}", menuMap.size());

        List<MenuVo> result = new ArrayList<>();
        menuMap.values().forEach(menu -> {
            Integer parentId = menu.getParentId();
            if (parentId == null || parentId == 0) {
                result.add(menu);
                log.debug("添加顶级菜单: ID={}, Name={}", menu.getMenuId(), menu.getName());
            } else {
                MenuVo parent = menuMap.get(parentId);
                if (parent != null) {
                    parent.getChildren().add(menu);
                    log.debug("添加子菜单: ID={}, Name={}, ParentID={}", 
                        menu.getMenuId(), menu.getName(), parentId);
                } else {
                    log.warn("子菜单找不到父菜单: MenuID={}, ParentID={}", menu.getMenuId(), parentId);
                    // 将没有父菜单的子菜单也作为顶级菜单返回
                    result.add(menu);
                }
            }
        });

        result.sort(Comparator.comparing(MenuVo::getMenuId));
        result.forEach(menu ->
                menu.getChildren().sort(Comparator.comparing(MenuVo::getMenuId)));

        log.info("构建菜单树完成，顶级菜单数量: {}", result.size());
        return result;
    }

    private List<MenuVo> buildFullMenuTree() {
        List<AllMenu> allMenus = queryAvailableMenus().list();
        return buildMenuTree(allMenus);
    }

    private List<MenuVo> queryChildMenus(Integer parentId) {
        return queryAvailableMenus()
                .eq(AllMenu::getParentId, parentId)
                .list()
                .stream()
                .map(MenuVo::new)
                .collect(Collectors.toList());
    }

    private boolean hasChildren(Integer menuId) {
        return allMenuMapper.exists(
                new LambdaQueryWrapper<AllMenu>().eq(AllMenu::getParentId, menuId));
    }

    private boolean isAdmin(Integer userId) {
        Integer roleId = allUserMapper.findUserRoleByUserId(userId);
        return roleId != null && roleId.equals(ADMIN_ROLE_ID);
    }

    private void validateMenu(AllMenuVo menu) {
        if (menu == null) {
            throw new IllegalArgumentException("菜单信息不能为空");
        }
        if (StringUtils.isBlank(menu.getMenuTitle())) {
            throw new IllegalArgumentException("菜单名称不能为空");
        }
        if (StringUtils.isBlank(menu.getMenuHref())) {
            throw new IllegalArgumentException("菜单路径不能为空");
        }
    }

    private void setCreatorInfo(AllMenuVo menuVo) {
        Integer currentUserId = UserContext.getUserId();
        if (currentUserId != null) {
            menuVo.setCreator(MENU_CREATOR_PREFIX + currentUserId);
            menuVo.setCreateTime(new Date());
        }
    }

    private void assignMenuToCurrentUserRole(Integer menuId, Integer userId) {
        if (userId == null || menuId == null) return;

        Integer roleId = allUserMapper.findUserRoleByUserId(userId);
        if (roleId != null) {
            RelRoleMenu relation = new RelRoleMenu();
            relation.setRoleId(roleId);
            relation.setMenuId(menuId);
            relRoleMenuMapper.insert(relation);
            log.info("菜单ID: {} 已分配给角色ID: {}", menuId, roleId);
        } else {
            log.warn("用户ID: {} 没有关联的角色，无法自动分配菜单权限", userId);
        }
    }

}




